﻿using System;
using System.Web.Mvc;
using ControleRepresentante.Logic;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.Logic.Statistics;
using WebSite.Controllers.ControllerExtensions;
using WebSite.ViewModels.DetailsViewModels;
using WebSite.ViewModels.EditViewModels;
using WebSite.ViewModels.IndexViewModels;
using Attribute = ControleRepresentante.Logic.Models.Attribute;

namespace WebSite.Controllers
{
    public class AttributeController : CRUDControllerBase<IAttributeRepository, Attribute, StatisticsBase>
    {
        public AttributeController(IRepositoryProvider repositoryProvider, ISessionConfiguration sessionConfiguration, IControllerExtensionProvider controllerExtensionProvider)
            : base(repositoryProvider, sessionConfiguration, controllerExtensionProvider)
        {
        }

        protected override Area? Area { get { return ControleRepresentante.Logic.Models.Area.Atributos; } }

        protected override IIndexViewModel GetIndexViewModel(StatisticsBase statistics)
        {
            return new AttributeIndexViewModel();
        }

        public ActionResult Search()
        {
            return Index();
        }

        protected override EditViewModel GetEditViewModel(Attribute model, bool isNew)
        {
            return new AttributeEditViewModel(isNew);
        }

        protected override DetailsViewModel GetDetailsViewModel(Attribute model)
        {
            return new AttributeDetailsViewModel();
        }

        protected override void RegisterIndexColumns(IIndexColumnsProvider indexColumnsProvider)
        {
            base.RegisterIndexColumns(indexColumnsProvider);
            indexColumnsProvider.SetDefaultColumns(
                indexColumnsProvider.RegisterColumn("Nome", AttributeIndexColumns.Nome, true),
                indexColumnsProvider.RegisterColumn("Tipo", AttributeIndexColumns.Tipo));
        }

        protected override Attribute CreateInstance()
        {
            Attribute attribute = base.CreateInstance();
            attribute.Representante = Repository.GetRepresentante();
            return attribute;
        }

        [HttpPost]
        public ActionResult Create(string name, string type)
        {
            EnsureHasPermission(Operacao.Create);
            if (TryUpdateAttribute(name, type))
            {
                try
                {
                    Repository.AddModel(Model);
                    Attribute attribute = Model;
                    Model = null;
                    return RedirectToAction("Details", attribute.Id);
                }
                catch (RepositoryException<AttributeError> e)
                {
                    switch (e.Error)
                    {
                        case AttributeError.DuplicatedName:
                            ModelState.AddModelError("Name", "Nome duplicado");
                            break;
                        default:
                            throw;
                    }
                }
            }
            return Create(false);
        }

        [HttpPost]
        public ActionResult Edit(string name)
        {
            EnsureHasPermission(Operacao.Update);
            if (TryUpdateAttribute(name, null))
            {
                try
                {
                    Repository.UpdateModel(Model);
                    Guid attributeId = Model.Id;
                    Model = null;
                    return RedirectToAction("Details", attributeId);
                }
                catch (RepositoryException<AttributeError> e)
                {
                    switch (e.Error)
                    {
                        case AttributeError.DuplicatedName:
                            ModelState.AddModelError("Name", "Nome duplicado");
                            break;
                        default:
                            throw;
                    }
                }
            }
            return Edit();
        }

        private bool TryUpdateAttribute(string name, string tipo)
        {
            if (tipo != null)
            {
                Model.Type = (AttributeType)Enum.Parse(typeof(AttributeType), tipo);
            }
            Model.Name = name;

            ModelState.Clear();
            if (String.IsNullOrEmpty(Model.Name) ||
                Model.Name.Trim() == String.Empty)
            {
                ModelState.AddModelError("Name", "*");
            }
            else if (Model.Name.Contains("_"))
            {
                ModelState.AddModelError("Name", "Nome nao pode conter '_'");
            }
            return ModelState.IsValid;
        }
    }
}
